package personal.vivian.logic;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import personal.vivian.aop.annotation.Transform;
import personal.vivian.aop.annotation.TransformParam;
import personal.vivian.builder.DataTemplate;
import personal.vivian.constants.EditMode;
import personal.vivian.constants.OperationStatus;
import personal.vivian.dto.Request;
import personal.vivian.interf.DataValdator;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class DataManager {
    private Map<Class<?>, DataTemplate> dataTemplateMapCache = new ConcurrentHashMap<>();
    private DataTemplate dataTemplate;

    public <T> T getThings(DataContext context, T item) {
        saveModel(context, item);
        return item;
    }
    public <T> T saveThings(DataContext context,T item){
        resoreModel(context,item);
        return item;
    }
    public <T> void saveModel(DataContext context, T item) {
        DataTemplate dataTemplate = getDataTemplate(item.getClass());
        if (dataTemplate.getHiddenItem() == null) {
            return;
        }
        JSONObject jsonObject = new JSONObject();

        for (TemplatItem templatItem : dataTemplate.getItems()) {
            if (templatItem.getEditMode() == null) {

            } else if (templatItem.getEditMode() != null && templatItem.getEditMode().equals(EditMode.None)) {

            } else {
                Field field = templatItem.getTargetField();
                field.setAccessible(true);
                try {
                    Object val = field.get(item);
                    jsonObject.put(field.getName(), JSON.toJSONString(val));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }
        Field targetField = dataTemplate.getHiddenItem().getTargetField();
        targetField.setAccessible(true);
        try {
            targetField.set(item, jsonObject.toString());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public <T> void resoreModel(DataContext context, T item) {
        DataTemplate dataTemplate = getDataTemplate(item.getClass());
        if (dataTemplate.getHiddenItem() == null) {
            return;
        }
        Field targetField = dataTemplate.getHiddenItem().getTargetField();
        targetField.setAccessible(true);
        for (TemplatItem templatItem : dataTemplate.getItems()) {
            if (templatItem.getEditMode() == null) {

            } else if (templatItem.getEditMode() != null && templatItem.getEditMode().equals(EditMode.None)) {

            } else if(templatItem.getEditMode().equals(EditMode.ReadOnly)){
                Field field = templatItem.getTargetField();
                field.setAccessible(true);
                try {
                    String object= (String) targetField.get(item);
                    JSONObject jsonObjec=JSON.parseObject(object);
                    Object o = jsonObjec.get(field.getName());
                    Class<?> type=field.getType();
                    field.set(item,o);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    public <T> T resovle(DataTemplate dataTemplate, DataContext context, T item) {
        for (TemplatItem item1 : dataTemplate.getItems()) {
            valdtor(context, item1, item);
        }

        return item;
    }
    public <T> T resovle(DataContext context, T item, OperationStatus status) {
        context.setStatus(status);
        DataTemplate dataTemplate = getDataTemplate(item.getClass());
        resovle(dataTemplate,context,item);
        return item;
    }
    public void addTemplate(DataTemplate dataTemplate) {
        dataTemplateMapCache.put(dataTemplate.getTemplateSource(), dataTemplate);
    }

    public DataTemplate getDataTemplate(Class<?> c) {
        return dataTemplateMapCache.get(c);
    }

    public <T> void valdtor(DataContext context, DataTemplate dataTemplate, T item) {
        for (TemplatItem templatItem : dataTemplate.getItems()) {
            valdtor(context, templatItem, item);
        }
    }

    public <T> void valdtor(DataContext context, TemplatItem item1, T item) {
        for (DataValdator dataValdator : item1.getDataValdators()) {
            try {
                dataValdator.valdtor(context, item, item1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public DataContext getContext(Object controller){
        DataContext dataContext = new DataContext();
        dataContext.setDataManager(this);
        dataContext.setTarget(controller);
        return dataContext;
    }
    @Transform(returnStatus = OperationStatus.None)
    public String saveItem(DataContext context,@TransformParam Request request){
        resoreModel(context,request);
        request.getName();
        return null;
    }
}
